<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>xeokit Example</title>
    <link href="../css/pageStyle.css" rel="stylesheet"/>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/js/all.min.js"></script>
</head>
<body>
<input type="checkbox" id="info-button"/>
<label for="info-button" class="info-button"><i class="far fa-3x fa-question-circle"></i></label>
<canvas id="myCanvas"></canvas>
<div class="slideout-sidebar">
    <img class="info-icon" src="../../assets/images/performance_model_icon.png"/>
    <h1>SceneModel</h1>
    <h2>Geometry batching and RTC coordinates</h2>
    <p>In this example, we're programmatically building a simple model using xeokit's SceneModel component, while
        at the same using a separate geometry for each object, and providing geometry vertex positions as
        relative-to-center (RTC) coordinates.</p>
    <p>RTC coordinates are xeokit's mechanism for full-precision emulation.</p>
    <h3>Components Used</h3>
    <ul>
        <li>
            <a href="../../docs/class/src/viewer/Viewer.js~Viewer.html"
               target="_other">Viewer</a>
        </li>
        <li>
            <a href="../../docs/class/src/viewer/scene/model/SceneModel.js~SceneModel.html"
               target="_other">SceneModel</a>
        </li>
    </ul>
</div>
</body>

<script type="module">

    //------------------------------------------------------------------------------------------------------------------
    // Import the modules we need for this example
    //------------------------------------------------------------------------------------------------------------------

    import {Viewer, SceneModel, math} from "../../dist/xeokit-sdk.min.es.js";

    //------------------------------------------------------------------------------------------------------------------
    // Create a Viewer and arrange the camera
    //------------------------------------------------------------------------------------------------------------------

    const viewer = new Viewer({
        canvasId: "myCanvas",
        transparent: true
    });

    //------------------------------------------------------------------------------------------------------------------
    // Enable data texture model representation for
    // all subsequently created SceneModels (unless they override it to be disabled)
    //------------------------------------------------------------------------------------------------------------------

    viewer.scene.dtxEnabled = true; // Default is false
    viewer.scene.dtx.indexBucketingEnabled = true; // Default
    viewer.scene.dtx.vertexWeldingEnabled = true; // Default

    //------------------------------------------------------------------------------------------------------------------
    // Create a SceneModel representing a table with four legs, using geometry batching
    //------------------------------------------------------------------------------------------------------------------

    const sceneModel = new SceneModel(viewer.scene, {
        id: "tables",
        isModel: true,
        scale: [1, 1, 1],
        rotation: [0, 0, 0],
        edges: true,
        dtxEnabled: true
    });

    //-----------------------------------------------------------
    // Create several origin points
    //-----------------------------------------------------------

    // const OFFSET = 1000000000.0;
    const OFFSET = 4.0;
    //const OFFSET = 100.0;

    const origins = [
        [0, 0, 0],
        [OFFSET, 0, 0],
        [0, 0, OFFSET],
        [OFFSET, 0, OFFSET]
    ];

    //-----------------------------------------------------------
    // Within out SceneModel, create a simple table model
    // at each of our origins. This will result in several
    // tables, positioned very far apart from each other.
    //-----------------------------------------------------------

    for (let i = 0, len = origins.length; i < len; i++) {
        buildTable(sceneModel, origins[i]);
    }

    //------------------------------------------------------------
    // Finalize the SceneModel.
    //------------------------------------------------------------

    sceneModel.finalize();

    viewer.cameraFlight.jumpTo(viewer.scene);

    //------------------------------------------------------------------------------------------------------------------
    // Creates a simple table-shaped model with the given SceneModel,
    // without reusing geometry, and centered at the given origin
    //------------------------------------------------------------------------------------------------------------------

    function buildTable(sceneModel, origin) {

        let meshId = math.createUUID();

        sceneModel.createMesh({
            id: meshId,
            origin: origin, // This mesh's positions and transforms are relative to the origin
            primitive: "triangles",
            positionsCompressed: [
                16381,60484,16381,
                5460,60484,16381,
                5460,0,16381,
                16381, 0,16381,
                16381, 60484,16381,
                16381, 0,16381,
                16381,0, 5460,
                16381,60484, 5460,
                16381,60484, 16381,
                16381,60484, 5460,
                5460,60484, 5460,
                5460,60484, 16381,
                5460,60484, 16381,
                5460,60484, 5460,
                5460,0, 5460,
                5460,0, 16381,
                5460,0, 5460,
                16381,0, 5460,
                16381,0, 16381,
                5460,0, 16381,
                16381,0, 5460,
                5460,0, 5460,
                5460,60484, 5460,
                16381,60484, 5460
            ],
            positionsDecodeMatrix: [
                0.00003052270125906143, 0, 0, 0,
                0, 0.00003052270125906143, 0, 0,
                0, 0, 0.00003052270125906143, 0,
                -1, -1, -1, 1
            ],
            indices: [
                0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15,
                16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23
            ],
            color: [1, 0.3, 0.3]
        });

        sceneModel.createEntity({
            meshIds: [meshId],
            isObject: true
        });

        meshId = math.createUUID();

        sceneModel.createMesh({
            id: meshId,
            origin: origin,
            primitive: "triangles",
            positionsCompressed: [
                60064,60484, 16381,
                49143,60484, 16381,
                49143,0, 16381,
                60064, 0, 16381,
                60064, 60484, 16381,
                60064, 0, 16381,
                60064, 0, 5460,
                60064, 60484, 5460,
                60064, 60484, 16381,
                60064, 60484, 5460,
                49143, 60484, 5460,
                49143, 60484, 16381,
                49143, 60484, 16381,
                49143, 60484, 5460,
                49143, 0, 5460,
                49143, 0, 16381,
                49143, 0, 5460,
                60064, 0, 5460,
                60064, 0, 16381,
                49143, 0, 16381,
                60064, 0, 5460,
                49143, 0, 5460,
                49143, 60484, 5460,
                60064, 60484, 5460
            ],
            positionsDecodeMatrix: [
                0.00003052270125906143, 0, 0, 0,
                0, 0.00003052270125906143, 0, 0,
                0, 0, 0.00003052270125906143, 0,
                -1, -1, -1, 1
            ],
            indices: [
                0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15,
                16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23
            ],
            color: [0.3, 1.0, 0.3]
        });

        sceneModel.createEntity({
            meshIds: [meshId],
            isObject: true
        });

        meshId = math.createUUID();

        sceneModel.createMesh({
            id: meshId,
            origin: origin,
            positionsCompressed: [
                60064, 60484, 60064,
                49143, 60484, 60064,
                49143, 0, 60064,
                60064, 0, 60064,
                60064, 60484, 60064,
                60064, 0, 60064,
                60064, 0, 49143,
                60064, 60484, 49143,
                60064, 60484, 60064,
                60064, 60484,49143,
                49143, 60484,49143,
                49143, 60484,60064,
                49143, 60484,60064,
                49143, 60484,49143,
                49143, 0,49143,
                49143, 0,60064,
                49143, 0,49143,
                60064, 0,49143,
                60064, 0,60064,
                49143, 0,60064,
                60064, 0,49143,
                49143, 0,49143,
                49143, 60484,49143,
                60064, 60484,49143
            ],
            positionsDecodeMatrix: [
                0.00003052270125906143, 0, 0, 0,
                0, 0.00003052270125906143, 0, 0,
                0, 0, 0.00003052270125906143, 0,
                -1, -1, -1, 1
            ],
            indices: [
                0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19,
                20, 21, 22, 20, 22, 23
            ],
            color: [0.3, 0.3, 1.0]
        });

        sceneModel.createEntity({
            meshIds: [meshId],
            isObject: true
        });

        meshId = math.createUUID();

        sceneModel.createMesh({
            id: meshId,
            origin: origin,
            positionsCompressed: [
                16381, 60484,60064,
                5460, 60484,60064,
                5460, 0,60064,
                16381, 0,60064,
                16381, 60484,60064,
                16381, 0,60064,
                16381, 0,49143,
                16381, 60484,49143,
                16381, 60484,60064,
                16381, 60484,49143,
                5460, 60484,49143,
                5460, 60484,60064,
                5460, 60484,60064,
                5460, 60484,49143,
                5460, 0,49143,
                5460, 0,60064,
                5460, 0,49143,
                16381, 0,49143,
                16381, 0,60064,
                5460, 0,60064,
                16381, 0,49143,
                5460, 0,49143,
                5460, 60484,49143,
                16381, 60484,49143
            ],
            positionsDecodeMatrix: [
                0.00003052270125906143, 0, 0, 0,
                0, 0.00003052270125906143, 0, 0,
                0, 0, 0.00003052270125906143, 0,
                -1, -1, -1, 1
            ],
            indices: [
                0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19,
                20, 21, 22, 20, 22, 23
            ],
            color: [1.0, 1.0, 0.0]
        });

        sceneModel.createEntity({
            meshIds: [meshId],
            isObject: true
        });

        meshId = math.createUUID();

        sceneModel.createMesh({
            id: meshId,
            origin: origin,
            positionsCompressed: [
                65525, 65525,65525,
                0, 65525,65525,
                0, 55444,65525,
                65525, 55444,65525,
                65525, 65525,65525,
                65525, 55444,65525,
                65525, 55444,0,
                65525, 65525,0,
                65525, 65525,65525,
                65525, 65525,0,
                0, 65525,0,
                0, 65525,65525,
                0, 65525,65525,
                0, 65525,0,
                0, 55444,0,
                0, 55444,65525,
                0, 55444,0,
                65525, 55444, 0,
                65525, 55444, 65525,
                0, 55444, 65525,
                65525, 55444, 0,
                0, 55444, 0,
                0, 65525, 0,
                65525, 65525,0
            ],
            positionsDecodeMatrix: [
                0.00003052270125906143, 0, 0, 0,
                0, 0.00003052270125906143, 0, 0,
                0, 0, 0.00003052270125906143, 0,
                -1, -1, -1, 1
            ],
            indices: [
                0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19,
                20, 21, 22, 20, 22, 23
            ],
            color: [1.0, 0.3, 1.0]
        });

        sceneModel.createEntity({
            meshIds: [meshId],
            isObject: true
        });
    }

</script>
</html>